package com.young.api;

import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.LineCaptcha;
import com.young.req.LoginReq;
import io.swagger.annotations.ApiOperation;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import javax.servlet.http.HttpServletResponse;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AccountException;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.CredentialsException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

/**
 * @Description: 登录相关
 * @Author: kangyang
 * @Date: 2021/5/8 18:12
 **/
@RestController
public class LoginController {

  @Autowired
  private RedisTemplate redisTemplate;

  private static final String LOGIN_CAPTCHA_UUID = "AUTH:CODE:";

  private static Logger log = LoggerFactory.getLogger(LoginController.class);

  @PostMapping("/login")
  @ApiOperation("登录")
  public ResponseEntity login(@RequestBody LoginReq loginReq) {
    String token = null;
    try {
      checkCaptcha(loginReq);
      UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(
          loginReq.getPrincipal(), loginReq.getCredentials());
      Subject subject = SecurityUtils.getSubject();
      subject.login(usernamePasswordToken);
      token = subject.getSession().getId().toString();
    } catch (AccountException e) {
      return ResponseEntity.badRequest().body("用户名不存在");
    } catch (CredentialsException e) {
      return ResponseEntity.badRequest().body("用户名或密码错误");
    } catch (AuthenticationException e) {
      e.printStackTrace();
      return ResponseEntity.badRequest().body(e.getMessage());
    }
    return ResponseEntity.ok(token);
  }

  /**
   * @Author kangyang
   * @Description 校验验证码
   * @Date 14:08 2021/5/12
   * @Param [loginReq]
   * @return void
   **/
  private void checkCaptcha(LoginReq loginReq) {
    String imageCode = loginReq.getImageCode();
    String sessionUUID = loginReq.getSessionUUID();
    if (StringUtils.isEmpty(imageCode)) {
      throw new AuthenticationException("请输入验证码");
    }
    Object redisCode = redisTemplate.opsForValue().get(LOGIN_CAPTCHA_UUID + sessionUUID);
    if (redisCode == null || !imageCode.equals(String.valueOf(redisCode))) {
      throw new AuthenticationException("验证码错误");
    }
  }

  @GetMapping("/captcha.jpg")
  @ApiOperation("获取验证码")
      public void captcha(String uuid, HttpServletResponse response) {
    log.info("获取验证码开始，uuid->{}", uuid);
    LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(150, 40, 4, 10);
    String code = lineCaptcha.getCode();
    log.info("验证码为{}, uuid->{}", code, uuid);
    redisTemplate.opsForValue().set(LOGIN_CAPTCHA_UUID + uuid, code, 60, TimeUnit.SECONDS);
    try {
      response.getOutputStream().write(lineCaptcha.getImageBytes());
    } catch (IOException e) {
      e.printStackTrace();
    }
    log.info("获取验证码结束，uuid->{}", uuid);
  }

  @PostMapping("/sys/logout")
  @ApiOperation("登出")
  public ResponseEntity logout(@RequestBody LoginReq loginReq) {
    String token = null;
    try {
      checkCaptcha(loginReq);
      UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(
          loginReq.getPrincipal(), loginReq.getCredentials());
      Subject subject = SecurityUtils.getSubject();
      subject.login(usernamePasswordToken);
      token = subject.getSession().getId().toString();
    } catch (AccountException e) {
      return ResponseEntity.badRequest().body("用户名不存在");
    } catch (CredentialsException e) {
      return ResponseEntity.badRequest().body("用户名或密码错误");
    } catch (AuthenticationException e) {
      e.printStackTrace();
      return ResponseEntity.badRequest().body(e.getMessage());
    }
    return ResponseEntity.ok(token);
  }


  @GetMapping("/index")
  @ApiOperation("访问主页")
  public String index() {
    return "index";
  }

  @GetMapping("/admin")
//  @RequiresRoles("admin")
  @ApiOperation("登录角色测试")
  public ResponseEntity admin() {
    return ResponseEntity.ok("admin");
  }

  @GetMapping("/user")
//  @RequiresRoles("user")
  @ApiOperation("登录其他角色测试")
  public ResponseEntity user() {
    return ResponseEntity.ok("user");
  }

  @GetMapping("/add")
//  @RequiresPermissions("admin:add")
  @ApiOperation("登录权限测试")
  public ResponseEntity add() {
    return ResponseEntity.ok("add");
  }

  @GetMapping("/insert")
//  @RequiresPermissions("sys:role:save")
  @ApiOperation("登录其他权限测试")
  public ResponseEntity insert() {
    return ResponseEntity.ok("insert");
  }
}
